package com.titan.core.utils.data;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;

/**
 * @author 周成功
 * @email 86898837@qq.com
 * @date 2020年02月14日
 */
public class DateUtils {
    private Calendar calendar;

    
    public DateUtils(long millis) {
        this.calendar = Calendar.getInstance();
        this.calendar.setTimeInMillis(millis);
    }
    public static DateUtils $(long millis) {
        return new DateUtils(millis);
    }
    public DateUtils(Calendar calendar) {
        this.calendar = calendar;
    }
    public static DateUtils $(Date date) {
        return new DateUtils(date);
    }
    public DateUtils(Date date) {
        this.calendar = Calendar.getInstance();
        this.calendar.setTime(date);        
    }    
    public static DateUtils $(String date, String pattern) throws ParseException {
        return new DateUtils(date, pattern);
    }
    public DateUtils(String date, String pattern) throws ParseException {
        this.calendar = Calendar.getInstance();
        this.calendar.setTime(FormatUtils.stringToDate(date, pattern));
    }
    public static DateUtils $() {
        return new DateUtils();
    }
    public DateUtils() {
        this.calendar = Calendar.getInstance();
    }
    
    
    // 解析成日期对象，并将为解析到的字段设置为允许设置的最大值
    public static DateUtils $Max(String date) throws ParseException {
        AssertUtils.assertNotEmpty(date, DateUtils.class, "$Max", "参数date");
        
        int len = date.length();
        if( len==23 ) {
            if( RegexUtils.isMatch("[0-9]{4}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]\\.[0-9]{3}", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy-MM-dd HH:mm:ss.SSS");
                return util;
            }
        } else if( len>=14 && len<=19 ) {
            if( RegexUtils.isMatch("[0-9]{4}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy-MM-dd HH:mm:ss");
                util.setMilliSecond(999);
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy-MM-dd HH:mm");
                util.setSecond(59);
                util.setMilliSecond(999);
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}[0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9][0-9]{3}", date) ) {
                DateUtils util = DateUtils.$(date, "yyyyMMddHHmmssSSS");
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}[0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyyMMddHHmmss");
                util.setMilliSecond(999);
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}/[0-1]{1,2}/[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy/M/d H:m:s");
                return util;
            }
        } else if( len==13 ) {
            if( RegexUtils.isMatch("[0-9]{13}", date) ) {
                DateUtils util = DateUtils.$(FormatUtils.toLong(date));
                return util;
            }
        } else if( len==12 ) {
            if( RegexUtils.isMatch("[0-2][0-9]:[0-5][0-9]:[0-5][0-9]\\.[0-9]{3}", date) ) {
                DateUtils util = DateUtils.$(date, "HH:mm:ss.SSS");
                return util;
            } else if( RegexUtils.isMatch("[0-9]{2}[0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyMMddHHmmss");
                return util;
            }
        } else if( len==10 ) {
            if( RegexUtils.isMatch("[0-9]{4}-[0-1][0-9]-[0-3][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy-MM-dd");
                util.setHour(23);
                util.setMinute(59);
                util.setSecond(59);
                util.setMilliSecond(999);
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}[0-1][0-9][0-3][0-9][0-2][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyyMMddHH");
                util.setMinute(59);
                util.setSecond(59);
                util.setMilliSecond(999);
                return util;
            }
        } else if( len==8 ) {
            if( RegexUtils.isMatch("[0-2][0-9]:[0-5][0-9]:[0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "HH:mm:ss");
                util.setMilliSecond(999);
                return util;
            }
            if( RegexUtils.isMatch("[0-9]{4}[0-1][0-9][0-3][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyyMMdd");
                util.setHour(23);
                util.setMinute(59);
                util.setSecond(59);
                util.setMilliSecond(999);
                return util;
            }
        } else if( len==6 ) {
            if( RegexUtils.isMatch("[0-2][0-9][0-5][0-9][0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "HHmmss");
                util.setMilliSecond(999);
                return util;
            }
        }
        AssertUtils.fail(DateUtils.class, "$Max", "未能有效的解析日期格式，date:["+date+"]");
        return null;
    }
    // 解析成日期对象，并将为解析到的字段设置为允许设置的最小值
    public static DateUtils $Min(String date) throws ParseException {
        AssertUtils.assertNotEmpty(date, DateUtils.class, "$Min", "参数date");
        
        int len = date.length();
        if( len==23 ) {
            if( RegexUtils.isMatch("[0-9]{4}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]\\.[0-9]{3}", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy-MM-dd HH:mm:ss.SSS");
                return util;
            }
        } else if( len>=14 && len<=19 ) {
            if( RegexUtils.isMatch("[0-9]{4}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy-MM-dd HH:mm:ss");
                util.setMilliSecond(0);
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy-MM-dd HH:mm");
                util.setSecond(0);
                util.setMilliSecond(0);
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}[0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9][0-9]{3}", date) ) {
                DateUtils util = DateUtils.$(date, "yyyyMMddHHmmssSSS");
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}[0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyyMMddHHmmss");
                util.setMilliSecond(0);
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}/[0-2]{1,2}/[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy/M/d H:m:s");
                return util;
            }
        } else if( len==13 ) {
            if( RegexUtils.isMatch("[0-9]{13}", date) ) {
                DateUtils util = DateUtils.$(FormatUtils.toLong(date));
                return util;
            }
        } else if( len==12 ) {
            if( RegexUtils.isMatch("[0-2][0-9]:[0-5][0-9]:[0-5][0-9]\\.[0-9]{3}", date) ) {
                DateUtils util = DateUtils.$(date, "HH:mm:ss.SSS");
                return util;
            } else if( RegexUtils.isMatch("[0-9]{2}[0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyMMddHHmmss");
                return util;
            }
        } else if( len==10 ) {
            if( RegexUtils.isMatch("[0-9]{4}-[0-1][0-9]-[0-3][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyy-MM-dd");
                util.setHour(0);
                util.setMinute(0);
                util.setSecond(0);
                util.setMilliSecond(0);
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}[0-1][0-9][0-3][0-9][0-2][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyyMMddHH");
                util.setMinute(0);
                util.setSecond(0);
                util.setMilliSecond(0);
                return util;
            }
        } else if( len==8 ) {
            if( RegexUtils.isMatch("[0-2][0-9]:[0-5][0-9]:[0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "HH:mm:ss");
                util.setMilliSecond(0);
                return util;
            } else if( RegexUtils.isMatch("[0-9]{4}[0-1][0-9][0-3][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "yyyyMMdd");
                util.setHour(0);
                util.setMinute(0);
                util.setSecond(0);
                util.setMilliSecond(0);
                return util;
            }
        } else if( len==6 ) {
            if( RegexUtils.isMatch("[0-2][0-9][0-5][0-9][0-5][0-9]", date) ) {
                DateUtils util = DateUtils.$(date, "HHmmss");
                util.setMilliSecond(0);
                return util;
            }
        }
        AssertUtils.fail(DateUtils.class, "$Min", "未能有效的解析日期格式，date:["+date+"]");
        return null;
    }    
    
    
    public String toString(String pattern) {
        return FormatUtils.dateToString(calendar.getTime(), pattern);
    }
    public String toString19OfYmdhms() {
        return FormatUtils.dateToString(calendar.getTime(), "yyyy-MM-dd HH:mm:ss");
    }
    public String toString17OfYmdhmss() {
        return FormatUtils.dateToString(calendar.getTime(), "yyyyMMddHHmmssSSS");
    }
    public String toString16OfYmdhm() {
        return FormatUtils.dateToString(calendar.getTime(), "yyyy-MM-dd HH:mm");
    }
    public String toString14OfYmdhms() {
        return FormatUtils.dateToString(calendar.getTime(), "yyyyMMddHHmmss");
    }
    public String toString12OfYmdhms() {
        return FormatUtils.dateToString(calendar.getTime(), "yyMMddHHmmss");
    }
    public String toString10OfYmd() {
        return FormatUtils.dateToString(calendar.getTime(), "yyyy-MM-dd");
    }
    public String toString8OfYmd() {
        return FormatUtils.dateToString(calendar.getTime(), "yyyyMMdd");
    }
    public String toString8OfHms() {
        return FormatUtils.dateToString(calendar.getTime(), "HH:mm:ss");
    }
    public String toString12OfHmss() {
        return FormatUtils.dateToString(calendar.getTime(), "HH:mm:ss.SSS");
    }
    public String toString6OfHms() {
        return FormatUtils.dateToString(calendar.getTime(), "HHmmss");
    }    
    
    public static DateUtils setYear(Date date, int year) {
        DateUtils util = new DateUtils(date);
        util.setYear(year);
        return util;
    }
    public DateUtils setYear(int year) {
        calendar.set(Calendar.YEAR, year);
        return this;
    }
    public static DateUtils setMonth(Date date, int month) {
        DateUtils util = new DateUtils(date);
        util.setMonth(month);
        return util;
    }
    // month : 1-12
    public DateUtils setMonth(int month) {
        calendar.set(Calendar.MONTH, month-1);
        return this;
    }
    public static DateUtils setDay(Date date, int day) {
        DateUtils util = new DateUtils(date);
        util.setDay(day);
        return util;
    }
    // day : 1-31
    public DateUtils setDay(int day) {
        calendar.set(Calendar.DAY_OF_MONTH, day);
        return this;
    }
    public static DateUtils setHour(Date date, int hour) {
        DateUtils util = new DateUtils(date);
        util.setHour(hour);
        return util;
    }
    public DateUtils setHour(int hour) {
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        return this;
    }
    public static DateUtils setMinute(Date date, int minute) {
        DateUtils util = new DateUtils(date);
        util.setMinute(minute);
        return util;
    }
    public DateUtils setMinute(int minute) {
        calendar.set(Calendar.MINUTE, minute);
        return this;
    }    
    public static DateUtils setSecond(Date date, int second) {
        DateUtils util = new DateUtils(date);
        util.setSecond(second);
        return util;
    }
    public DateUtils setSecond(int second) {
        calendar.set(Calendar.SECOND, second);
        return this;
    }
    public static DateUtils setMilliSecond(Date date, int millisecond) {
        DateUtils util = new DateUtils(date);
        util.setMilliSecond(millisecond);
        return util;
    }
    public DateUtils setMilliSecond(int millisecond) {
        calendar.set(Calendar.MILLISECOND, millisecond);
        return this;
    }
    
    public Date getDate() {
        return new Date(calendar.getTimeInMillis());
    }    
    
    
    
    public static String toStringMilliSecondToHms(long millis) {
        long hourResult = millis/3600000;
        long minuteResult = (millis - hourResult*3600000) / 60000;
        long secondResult = (millis - hourResult*3600000 - minuteResult*60000) / 1000;
        long millisResult = millis - hourResult*3600000 - minuteResult*60000 - secondResult*1000;
        if(hourResult>0)  {
            return hourResult + "时 " + FormatUtils.to2Digit(minuteResult) + "分 " + FormatUtils.to2Digit(secondResult) + "秒 " + FormatUtils.to3Digit(millisResult) + "毫秒";
        } else if(minuteResult>0) {
            return minuteResult + "分 " + FormatUtils.to2Digit(secondResult) + "秒 " + FormatUtils.to3Digit(millisResult) + "毫秒";
        } else if(secondResult>0) {
            return StringUtils.append(secondResult, "秒", FormatUtils.to3Digit(millisResult), "毫秒");
        }
        return millisResult + "毫秒";
    }    
    
    
    
}
